#include "stdafx.h"
#include "PapaBallSceneManager.h"
#include "utility.h"
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#include "../res/resource.h"
#endif

#include "InputManager.h"
#include <CEGUI.h>

#include "testScene.h"
#include "MainMenu.h"
#include "GameMode1Scene.h"
#include "Character.h"
#include "ParticleSys.h"
#include "NormalMode.h"
#include "timer/TimerManager.h"
using namespace Ogre;


PapaBallSceneManager* Singleton<PapaBallSceneManager>::ms_Singleton = 0;
PapaBallSceneManager g_PapaBall_manager;

CEGUI::MouseButton convertButton(OIS::MouseButtonID buttonID)
{
	switch (buttonID)
	{
	case OIS::MB_Left:
		return CEGUI::LeftButton;

	case OIS::MB_Right:
		return CEGUI::RightButton;

	case OIS::MB_Middle:
		return CEGUI::MiddleButton;

	default:
		return CEGUI::LeftButton;
	}
}

PapaBallSceneManager::PapaBallSceneManager()
	:mSceneMgr(0),
	mMouse(0),
	mKeyboard(0),
	mRoot(0),
	//mSceneMgr(0),
	mWindow(0),
	mCursorWasVisible(false),
	mShutDown(false),
	mCamera(0),
	mCameraMan(0),
	mMenuMgr(0),
	bChangeScene(false)
{
}
PapaBallSceneManager::~PapaBallSceneManager()
{
	Ogre::WindowEventUtilities::removeWindowEventListener(mWindow, this);
	windowClosed(mWindow);
}

#pragma region Listener

bool PapaBallSceneManager::frameStarted(const FrameEvent& evt)
{
	if(bChangeScene)
	{
		if(SwitchSceneName == "MainScene")
		{
			ChangeScene(new MainScene(mSceneEvn));
		}
		else if (SwitchSceneName == "Mode1")
		{
			ChangeScene(new GameMode1Scene(mSceneEvn));
		}
		else 
			ChangeScene(new NormalMode(mSceneEvn));
		bChangeScene = false;
	}
	if(this->m_current_scene!=NULL)
		return m_current_scene->frameStarted(evt);
	return true;
}
bool PapaBallSceneManager::frameRenderingQueued(const Ogre::FrameEvent& evt)
{
	if(mWindow->isClosed())
		return false;

	if(mShutDown)
		return false;

	//Need to capture/update each device
	PapaBallInputManager::getSingleton().CaptureAll();
//	pNui->capture();

	if(!Kinect::getSingleton().isPause && !Kinect::getSingleton().isDown)
	{
		Kinect::getSingleton().m_Context.WaitNoneUpdateAll();
		Kinect::getSingleton().m_pSessionManager->Update(&Kinect::getSingleton().m_Context);
	}

	CEGUI::System::getSingleton().injectTimePulse(evt.timeSinceLastFrame);
	if(this->m_current_scene!=NULL)
		return m_current_scene->frameRenderingQueued(evt);
	return true;
}
bool PapaBallSceneManager::frameEnded(const FrameEvent& evt)
{
	if(this->m_current_scene!=NULL)
		return m_current_scene->frameRenderingQueued(evt);
	return true;
}

bool PapaBallSceneManager::keyPressed( const KeyEvent &arg )
{
	if(MenuManager::getSingleton().IsMenuActive())
	{
		CEGUI::System &sys = CEGUI::System::getSingleton();
		sys.injectKeyDown(arg.key);
		sys.injectChar(arg.text);
		return true;
	}
	if(this->m_current_scene!=NULL)
		return m_current_scene->keyPressed(arg);
	return true;
}
bool PapaBallSceneManager::keyReleased( const KeyEvent &arg )
{
	if(MenuManager::getSingleton().IsMenuActive())
	{
		CEGUI::System::getSingleton().injectKeyUp(arg.key);
		return true;
	}
	if(m_current_scene!=NULL)
		return m_current_scene->keyReleased(arg);
	return true;
}

bool PapaBallSceneManager::mouseMoved( const MouseEvent &arg )
{
	if(MenuManager::getSingleton().IsMenuActive())
	{
		CEGUI::System &sys = CEGUI::System::getSingleton();
		sys.injectMouseMove(arg.state.X.rel, arg.state.Y.rel);
		// Scroll wheel.
		if (arg.state.Z.rel)
			sys.injectMouseWheelChange(arg.state.Z.rel / 120.0f);
		return true;
	}
	if(m_current_scene!= NULL)
		m_current_scene->mouseMoved(arg);
	return true;
}
bool PapaBallSceneManager::mousePressed( const MouseEvent &arg, MouseButtonID id )
{

	if(MenuManager::getSingleton().IsMenuActive())
	{
		CEGUI::System::getSingleton().injectMouseButtonDown(convertButton(id));
		return true;
	}
	if(m_current_scene!=NULL)
		return m_current_scene->mousePressed(arg,id);
	return true;
}
bool PapaBallSceneManager::mouseReleased( const MouseEvent &arg, MouseButtonID id )
{
	if(MenuManager::getSingleton().IsMenuActive())
	{
		CEGUI::System::getSingleton().injectMouseButtonUp(convertButton(id));
		return true;
	}
	if(m_current_scene!=NULL)
		return m_current_scene->mouseReleased(arg,id);
	return true;
}
#pragma endregion Listener



void PapaBallSceneManager::setup()
{
	//setupResources();
	//setupWindow();
	PRINT("SceneManager:Initialization Start");
	chooseSceneManager();
	createCamera();
	createViewports();
	// Set default mipmap level (NB some APIs ignore this)
	Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(5);

	createFrameListener();

	mMenuMgr = MenuManager::getSingletonPtr();
	PRINT("SceneManager:Initialization End");
	
	mSceneEvn.mCamera = mCamera;
	mSceneEvn.mMouse = mMouse;
	mSceneEvn.mSceneMgr = mSceneMgr;
	mSceneEvn.mKeyboard = mKeyboard;
	mSceneEvn.mCameraMan = mCameraMan;
	mSceneEvn.mViewport = mViewport;
//	setScene("123");
	setScene("MainScene");
//	setScene("Character");
//	setScene("Mode1");
//	pNui= new NuiWrap();
//	pNui->_initialize();
//	setScene("MainScene");
}
void PapaBallSceneManager::createFrameListener()
{

	Ogre::LogManager::getSingletonPtr()->logMessage("*** Initializing OIS ***");
	OIS::ParamList pl;
	size_t windowHnd = 0;
	std::ostringstream windowHndStr;

	mWindow->getCustomAttribute("WINDOW", &windowHnd);
	windowHndStr << windowHnd;
	pl.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str()));
		
	PapaBallInputManager::getSingleton().CreateInputManager(pl);
	mInputManager = PapaBallInputManager::getSingleton().GetInputMgr();
	mMouse = PapaBallInputManager::getSingleton().GetMouseDevice();
	mKeyboard = PapaBallInputManager::getSingleton().GetKeyBoardDevice();

	mMouse->setEventCallback(this);
	mKeyboard->setEventCallback(this);

	
	//Set initial mouse clipping size
	windowResized(mWindow);

	//Register as a Window listener
	Ogre::WindowEventUtilities::addWindowEventListener(mWindow, this);
	mRoot->addFrameListener(this);
	mRoot->addFrameListener(&TimerManager::getSingleton());
}
void PapaBallSceneManager::chooseSceneManager()
{
	mSceneMgr = mRoot->createSceneManager("OctreeSceneManager");
}
void PapaBallSceneManager::createViewports()
{
	// Create one viewport, entire window
	mViewport = mWindow->addViewport(mCamera);
	mViewport->setBackgroundColour(Ogre::ColourValue(0,0,0));

	// Alter the camera aspect ratio to match the viewport
	mCamera->setAspectRatio(
		Ogre::Real(mViewport->getActualWidth()) / Ogre::Real(mViewport->getActualHeight()));
}
void PapaBallSceneManager::windowClosed(Ogre::RenderWindow* rw)
{
	//Only close for window that created OIS (the main window in these demos)
	if( rw == mWindow )
	{
		if( mInputManager )
		{
			mInputManager->destroyInputObject( mMouse );
			mInputManager->destroyInputObject( mKeyboard );

			OIS::InputManager::destroyInputSystem(mInputManager);
			mInputManager = 0;
		}
	}
}
void PapaBallSceneManager::windowResized(Ogre::RenderWindow* rw)
{
	unsigned int width, height, depth;
	int left, top;
	rw->getMetrics(width, height, depth, left, top);

	const OIS::MouseState &ms = mMouse->getMouseState();
	ms.width = width;
	ms.height = height;
}
void PapaBallSceneManager::createCamera()
{
	mCamera = mSceneMgr->createCamera("PlayerCam");

	// Position it at 500 in Z direction
	mCamera->setPosition(Ogre::Vector3(0,0,5));
	// Look back along -Z
	mCamera->lookAt(Ogre::Vector3(0,0,-300));
	mCamera->setNearClipDistance(5);

	mCameraMan = new OgreBites::SdkCameraMan(mCamera);   // create a default camera controller
}
void PapaBallSceneManager::setupWindow()
{
	mRoot = Ogre::Root::getSingletonPtr();
	mWindow = mRoot->initialise(true, "Welcome To PapaBall!");

	// Let's add a nice window icon
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
	HWND hwnd;
	mWindow->getCustomAttribute("WINDOW", (void*)&hwnd);
	LONG iconID   = (LONG)LoadIcon( GetModuleHandle(0), MAKEINTRESOURCE(IDI_APPICON) );
	SetClassLong( hwnd, GCL_HICON, iconID );
#endif
}

std::string PapaBallSceneManager::getCurrentSceneName()
{
	return SwitchSceneName;
}

void PapaBallSceneManager::setScene(std::string name)
{
	this->SwitchSceneName = name;
	this->bChangeScene=true;
	//if(name == "MainScene")
	//{
	//	ChangeScene(new MainScene(mSceneEvn));
	//}
	//else if (name == "Mode1")
	//{
	//	ChangeScene(new GameMode1Scene(mSceneEvn));
	//}
	//else if (name == "ParticleSys")
	//{
	//	ChangeScene(new ParticleSys(mSceneEvn));
	//}
	//else if (name == "Character")
	//{
	//	ChangeScene(new Character(mSceneEvn));
	//}
	//else
	//	ChangeScene((new NormalMode(mSceneEvn)));
}

void PapaBallSceneManager::ChangeScene(Scene *scene)
{
	if(m_current_scene!=NULL)
	{
		m_current_scene->destroyScene();
		delete m_current_scene;
		m_current_scene = NULL;
	}
	

	this->m_current_scene = scene;
	m_current_scene->Initialization();
}